/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package berlin.volders.rxdiff2;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.DependentLayout;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.app.dispatcher.TaskDispatcher;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static berlin.volders.rxdiff2.ThingRepository.*;

/**
 * CustomTableLayout.
 *
 * @since 2021-06-29
 */
public class CustomTableLayout extends DependentLayout {
    private List<Component> dependentLayouts;
    private TaskDispatcher taskDispatcher;
    private List<Integer> cycleList;
    private TableRunnable tableRunnable;
    private List<Component> tempList;
    private boolean isAdd = false;
    private BaseProvider mBaseProvider;
    private ChangeDataListener changeDataListener;

    /**
     * MyRunnable.
     *
     * @since 2021-06-29
     */
    private class TableRunnable implements Runnable {
        @Override
        public void run() {
            if (tempList.size() > 0) {
                tempList.clear();
            }
            if (cycleList.size() > 0) {
                cycleList.clear();
            }
            int cycleNumber = ThingRepository.randomCycleNumber();
            int countCycle = 0;
            while (countCycle < cycleNumber) {
                int disappearIndex = ThingRepository.randomlyGenerated(mBaseProvider.count());
                if (!cycleList.contains(disappearIndex)) {
                    cycleList.add(disappearIndex);
                    countCycle++;
                }
            }
            tempList.addAll(dependentLayouts);
            Collections.shuffle(dependentLayouts); // 将集合随机打乱
            hiddenTable(0f, 0, cycleNumber);
        }

        private void tableMove(int cycleNumber) {
            for (int ii = 0; ii < tempList.size(); ii++) {
                for (int jj = 0; jj < dependentLayouts.size(); jj++) {
                    if (tempList.get(ii) == dependentLayouts.get(jj)) {
                        AnimatorProperty property = new AnimatorProperty();
                        property.setTarget(tempList.get(ii))
                                .moveFromX(tempList.get(ii).getContentPositionX())
                                .moveFromY(tempList.get(ii).getContentPositionY())
                                .moveToX(tempList.get(jj).getContentPositionX())
                                .moveToY(tempList.get(jj).getContentPositionY())
                                .setDuration(DURATION);
                        int finalI = ii;
                        property.setStateChangedListener(new CustStateChangedListener() {
                            @Override
                            public void onEnd(Animator animator) {
                                super.onEnd(animator);
                                if ((mBaseProvider.count() - 1) == finalI) {
                                    hiddenTable(1.0f, 1, cycleNumber);
                                }
                            }

                            @Override
                            public void onStart(Animator animator) {
                                super.onStart(animator);
                                if (changeDataListener != null) {
                                    changeDataListener.changeData(tempList.get(finalI), finalI);
                                }
                            }

                            @Override
                            public void onResume(Animator animator) {
                                super.onResume(animator);
                            }

                            @Override
                            public void onStop(Animator animator) {
                                super.onStop(animator);
                                property.stop();
                            }
                        });
                        property.start();
                    }
                }
            }
        }

        private void hiddenTable(float alpha, int flag, int cycleNumber) {
            int disCom = 0;
            for (int ii = 0; ii < tempList.size(); ii++) {
                for (Integer integer : cycleList) {
                    if (ii == integer) {
                        disCom++;
                        AnimatorProperty property = new AnimatorProperty();
                        property.setTarget(tempList.get(ii))
                                .alpha(alpha)
                                .setDuration(DURATION);
                        int finalDisCom = disCom;
                        property.setStateChangedListener(new CustStateChangedListener() {
                            @Override
                            public void onEnd(Animator animator) {
                                super.onEnd(animator);
                                if (flag == 0 && finalDisCom == cycleNumber) {
                                    tableMove(cycleNumber);
                                }
                            }

                            @Override
                            public void onStop(Animator animator) {
                                super.onStop(animator);
                                property.stop();
                            }
                        });
                        property.start();
                    }
                }
            }
        }
    }

    /**
     * CustomTableLayout
     *
     * @param context Context
     */
    public CustomTableLayout(Context context) {
        super(context);
    }

    /**
     * CustomTableLayout
     *
     * @param context Context
     * @param attrSet AttrSet
     */
    public CustomTableLayout(Context context, AttrSet attrSet) {
        super(context, attrSet);
    }

    /**
     * CustomTableLayout
     *
     * @param context Context
     * @param attrSet AttrSet
     * @param styleName String
     */
    public CustomTableLayout(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
    }

    /**
     * 设置数据
     *
     * @param context Context
     * @param baseProvider BaseProvider
     */
    public void setProvider(Context context, BaseProvider baseProvider) {
        mBaseProvider = baseProvider;
        initView(context);
    }

    private void initView(Context context) {
        if (cycleList == null) {
            cycleList = new ArrayList<>();
        }

        if (tempList == null) {
            tempList = new ArrayList<>();
        }
        if (!isAdd) {
            if (dependentLayouts == null) {
                dependentLayouts = new ArrayList<>();
            }
            for (int ii = 0; ii < mBaseProvider.count(); ii++) {
                Component dependentLayout = mBaseProvider.getComponent(ii, null, this);
                dependentLayouts.add(dependentLayout);
            }
            initData(context);
        }
        if (taskDispatcher == null) {
            taskDispatcher = context.getUITaskDispatcher();
        }
        if (tableRunnable == null) {
            tableRunnable = new TableRunnable();
        }
    }

    /**
     * 循环发送
     */
    public void sendDelayDispatch() {
        taskDispatcher.asyncDispatch(tableRunnable);
    }

    private void initData(Context context) {
        int hh = 0;
        int widthTable = DisplayManager.getInstance()
                .getDefaultDisplay(context).get()
                .getRealAttributes().width / SEVEN;
        for (int ii = 0; ii < dependentLayouts.size(); ii++) {
            if (ii % SEVEN == 0 && ii != 0) {
                hh += COUNT;
            }
            dependentLayouts.get(ii).setWidth(widthTable);
            dependentLayouts.get(ii).setMarginLeft(ii % SEVEN * widthTable);
            dependentLayouts.get(ii).setMarginTop(hh);
            addComponent(dependentLayouts.get(ii));
        }
        isAdd = true;
    }

    public void setChangeDataListener(ChangeDataListener changeDataListener) {
        this.changeDataListener = changeDataListener;
    }

    /**
     * ChangeDataListener.
     *
     * @since 2021-06-29
     */
    public interface ChangeDataListener {
        /**
         * 刷新数据
         *
         * @param component Component
         * @param position int
         */
        void changeData(Component component, int position);
    }
}
